use std::fmt;

struct Structure(i32);

// 为了使用 `{}` 标记，必须手动为类型实现 `fmt::Display` trait。
impl fmt::Display for Structure {
    // 这个 trait 要求 `fmt` 使用与下面的函数完全一致的函数签名
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // 仅将 self 的第一个元素写入到给定的输出流 `f`。返回 `fmt:Result`，此结果表明操作成功或失败。注意 `write!` 的用法和 `println!` 很相似。
        write!(f, "{}", self.0)
    }
}

//----------------------------------------------------------------------------------------//
#[derive(Debug)]
struct MinMax(i64, i64);

// 实现 `MinMax` 的 `Display`。
impl fmt::Display for MinMax {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // 使用 `self.number` 来表示各个数据。
        write!(f, "({}, {})", self.0, self.1)
    }
}

//------------------------------------------------------------------------------------------//
// 为了比较，定义一个含有具名字段的结构体。
#[derive(Debug)]
struct Point2D {
    x: f64,
    y: f64,
}

// 类似地对 `Point2D` 实现 `Display`
impl fmt::Display for Point2D {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // 自定义格式，使得仅显示 `x` 和 `y` 的值。
        write!(f, "x: {}, y: {}", self.x, self.y)
    }
}

//------------------------------------------------------------------------------------------//
impl fmt::Binary for Point2D {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "x: {:b}, y: {:b}", self.x as i32, self.y as i32)
  }
}

fn main() {
  let st = Structure(12);
  println!("Display: {}", st);
  // `Structure` cannot be formatted using `{:?}`
  //println!("Debug: {:?}", st);

  let minmax = MinMax(0, 14);

  println!("");
  println!("Compare structures:");
  println!("Display: {}", minmax);
  println!("Debug: {:?}", minmax);


  let point = Point2D { x: 3.3, y: 7.2 };

  println!("");
  println!("Compare points:");
  println!("Display: {}", point);
  println!("Debug: {:?}", point);

  // `{:b}` 需要 `fmt::Binary`
  println!("What does Point2D look like in binary: {:b}?", point);
}